package com.pervasa.demo.kitsample.impl;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.pervasa.demo.kitsample.impl.AtlasReactiveEngine.AtomicEvent;

public class TerminalEvent extends EventTree {
	public TerminalEvent(String expression, DataHistoryManager dhm) throws Exception
	{
		this.expression = expression;
		this.dhm = dhm;
		parseTerminal();
	}
	
	private void parseTerminal() throws Exception {
		int index1 = expression.indexOf('[');
		int index2 = expression.indexOf('(');
		if (index1 != -1 || index2 != -1)
		{
			int index = index1 != -1 ? index1 : index2;
			
			sensorId = expression.substring(0,index);
			valuePart = expression.substring(index);
			parseValuePart();
			return;
		}
		else 
			ThrowExpressionException();
	}
	
	private void parseValuePart() throws Exception {
		Pattern p1 = Pattern.compile("^\\(([-]?\\d+)\\)$");
		Matcher m1 = p1.matcher(valuePart);
		
		Pattern p2 = Pattern.compile("^\\[([-]?\\d+),([-]?\\d+)\\]$");
		Matcher m2 = p2.matcher(valuePart);
		
		if (m1.matches()) 
		{
			this.isEqualExpression = true;
			this.isRangeExpression = false;
		    this.equalValue = Integer.parseInt(m1.group(1));
		}
		else if (m2.matches())
		{
			this.isEqualExpression = false;
			this.isRangeExpression = true;
			
			this.startValue = Integer.parseInt(m2.group(1));
			this.endValue = Integer.parseInt(m2.group(2));
		}
		else 
		{
			ThrowExpressionException();
		}

	}

	public void ThrowExpressionException() throws Exception
	{
		throw new Exception("expression " + expression + " is not for terminal node");
	}

	public void setTruth(TRUTH truth) {
		this.truth = truth;
	}
	
	public void setTruth(int sensorValue)
	{
		if (isEqualExpression)
		{
			if (sensorValue == equalValue)
				this.truth = TRUTH.TRUE;
			else
				this.truth = TRUTH.FALSE;
		}
		else
		{
			if (sensorValue >= startValue && sensorValue <= endValue)
				this.truth = TRUTH.TRUE;
			else
				this.truth = TRUTH.FALSE;
		}
	}
	
	public void setTruth(int startSensorValue, int endSensorValue)
	{
		if (isEqualExpression)
		{
			if (startSensorValue == equalValue && endSensorValue == equalValue)
				this.truth = TRUTH.TRUE;
			else
				this.truth = TRUTH.FALSE;
		}
		else
		{
			if (startSensorValue >= startValue && endSensorValue <= endValue)
				this.truth = TRUTH.TRUE;
			else
				this.truth = TRUTH.FALSE;
		}
	}

	public TRUTH evaluate() {
		return truth;
	}
	private TRUTH truth = TRUTH.UNKNOWN;
	
	private String expression = "";
	
	private String sensorId = "";
	//(NUM) || [NUM,NUM]
	private String valuePart = "";
	boolean isEqualExpression = false;
	boolean isRangeExpression = false;
	int equalValue = 0;
	int startValue = 0;
	int endValue = 0;
	DataHistoryManager dhm = null;
	
	public boolean isRangeEvent()
	{
		return isRangeExpression;
	}
	public int getEqualValue()
	{
		return equalValue;
	}
	public int getStartValue()
	{
		return startValue;
	}
	public int getEndValue()
	{
		return endValue;
	}
	public String getSensorId()
	{
		return sensorId;
	}
//		a = new AtomicEvent("e1","","W47(500)");
//		a = new AtomicEvent("e2","", "S42[400,600]");
//		a = new AtomicEvent("e3", "j56(60)+e1*e2", "gh4(60)+W47(500)*5*S42[400,600]");
	public boolean isPullEvent() 
	{
		return isSensorPulling;
	}
	
	public void setPullEvent(boolean isPulling)
	{
		isSensorPulling = isPulling;
	}
	boolean isSensorPulling = false;

	public double getProbability() {
		double hitProb = dhm.getProbability(this);
		if (this.truth == TRUTH.TRUE)
			return hitProb;
		else if (this.truth == TRUTH.FALSE)
			return 1.0 - hitProb;
		else
			return 1.0;
	}
}
